//                        date: [[20120731120201]]
//                        Author: Ahmed Fathi Hamouda Abd El Hafez
using System;
using System.ComponentModel;
using System.Reflection;
using System.Data;
using System.Diagnostics;
using CustomersSuppliersDataLayer;
using System.Collections.Generic;


namespace CustomersSuppliersBusinessLayer
{
    /// <summary>
    ///  Business Object OF Table Products
    /// </summary>

    [Serializable]
    public partial class BLProduct : INotifyPropertyChanged
    {
        #region Fields

        protected DLProduct f_DLProduct = new DLProduct();

        protected Exception f_Error = null;

        protected BusinessObjectState f_State = BusinessObjectState.Created;

        protected Dictionary<string, object> extendedProperties = new Dictionary<string, object>();

        protected Dictionary<string, BLProduct> RestorePoints = new Dictionary<string, BLProduct>();

        #endregion

        #region constructors

        /// <summary>
        ///  initialize new insance from BLProduct with no values ( all properties are set to null)
        /// </summary>
        public BLProduct()
        {

        }


        /// <summary>
        ///  initialize new insance from BLProduct with DLProduct
        /// </summary>
        internal BLProduct(DLProduct DLProduct, BusinessObjectState state)
        {
            this.f_DLProduct = DLProduct;
            this.f_State = state;
            this.f_Error = DLProduct.Error;
        }

        /// <summary>
        ///  initialize new insance from BLProduct.
        /// </summary>
        public BLProduct(
        int? Product_RowNumber,  
        Guid? Product_ID,  
        string Product_Code,  
        Guid? ProductClassification_ID,  
        string Product_NameAr,  
        string Product_NameEn,  
        string Product_Notes,  
        string Product_Search,  
        byte[] Product_TimeStamp
)
            : this()
        {
            this.Product_RowNumber = Product_RowNumber;
            this.Product_ID = Product_ID;
            this.Product_Code = Product_Code;
            this.ProductClassification_ID = ProductClassification_ID;
            this.Product_NameAr = Product_NameAr;
            this.Product_NameEn = Product_NameEn;
            this.Product_Notes = Product_Notes;
            this.Product_Search = Product_Search;
            this.Product_TimeStamp = Product_TimeStamp;
        }


        /// <summary>
        ///  initialize new insance from BLProduct.
        /// </summary>
        public BLProduct(
        Guid? Product_ID
        )
            : this()
        {
            this.Product_ID = Product_ID;
            }

        #endregion

        #region properties
        /// <summary>
        /// Gets or sets the _ColumName_ value.
        /// </summary>
        public int? Product_RowNumber
        {
            get
            {
                return this.DLProduct.Product_RowNumber;
            }
            set
            {
                if (this.Product_RowNumber != value)
                {
                    this.DLProduct.Product_RowNumber = value;
                    this.OnPropertyChanged(BLProduct.PropertiesNames.Product_RowNumber);
                }
            }
        }
        /// <summary>
        /// Gets or sets the _ColumName_ value.
        /// </summary>
        public Guid? Product_ID
        {
            get
            {
                return this.DLProduct.Product_ID;
            }
            set
            {
                if (this.Product_ID != value)
                {
                    this.DLProduct.Product_ID = value;
                    this.OnPropertyChanged(BLProduct.PropertiesNames.Product_ID);
                }
            }
        }
        /// <summary>
        /// Gets or sets the _ColumName_ value.
        /// </summary>
        public string Product_Code
        {
            get
            {
                return this.DLProduct.Product_Code;
            }
            set
            {
                if (this.Product_Code != value)
                {
                    this.DLProduct.Product_Code = value;
                    this.OnPropertyChanged(BLProduct.PropertiesNames.Product_Code);
                }
            }
        }
        /// <summary>
        /// Gets or sets the _ColumName_ value.
        /// </summary>
        public Guid? ProductClassification_ID
        {
            get
            {
                return this.DLProduct.ProductClassification_ID;
            }
            set
            {
                if (this.ProductClassification_ID != value)
                {
                    this.DLProduct.ProductClassification_ID = value;
                    this.OnPropertyChanged(BLProduct.PropertiesNames.ProductClassification_ID);
                }
            }
        }
        /// <summary>
        /// Gets or sets the _ColumName_ value.
        /// </summary>
        public string Product_NameAr
        {
            get
            {
                return this.DLProduct.Product_NameAr;
            }
            set
            {
                if (this.Product_NameAr != value)
                {
                    this.DLProduct.Product_NameAr = value;
                    this.OnPropertyChanged(BLProduct.PropertiesNames.Product_NameAr);
                }
            }
        }
        /// <summary>
        /// Gets or sets the _ColumName_ value.
        /// </summary>
        public string Product_NameEn
        {
            get
            {
                return this.DLProduct.Product_NameEn;
            }
            set
            {
                if (this.Product_NameEn != value)
                {
                    this.DLProduct.Product_NameEn = value;
                    this.OnPropertyChanged(BLProduct.PropertiesNames.Product_NameEn);
                }
            }
        }
        /// <summary>
        /// Gets or sets the _ColumName_ value.
        /// </summary>
        public string Product_Notes
        {
            get
            {
                return this.DLProduct.Product_Notes;
            }
            set
            {
                if (this.Product_Notes != value)
                {
                    this.DLProduct.Product_Notes = value;
                    this.OnPropertyChanged(BLProduct.PropertiesNames.Product_Notes);
                }
            }
        }
        /// <summary>
        /// Gets or sets the _ColumName_ value.
        /// </summary>
        public string Product_Search
        {
            get
            {
                return this.DLProduct.Product_Search;
            }
            set
            {
                if (this.Product_Search != value)
                {
                    this.DLProduct.Product_Search = value;
                    this.OnPropertyChanged(BLProduct.PropertiesNames.Product_Search);
                }
            }
        }
        /// <summary>
        /// Gets or sets the _ColumName_ value.
        /// </summary>
        public byte[] Product_TimeStamp
        {
            get
            {
                return this.DLProduct.Product_TimeStamp;
            }
            set
            {
                if (this.Product_TimeStamp != value)
                {
                    this.DLProduct.Product_TimeStamp = value;
                    this.OnPropertyChanged(BLProduct.PropertiesNames.Product_TimeStamp);
                }
            }
        }

        /// <summary>
        ///  get the data layer object 
        /// </summary>
        internal DLProduct DLProduct
        {
            get
            {
                return this.f_DLProduct;
            }
        }

        /// <summary>
        /// get the error ocured after insert or update or delete or load
        /// </summary>
        public Exception Error
        {
            get { return this.f_DLProduct.Error; }
        }

        /// <summary>
        /// gets the state of this object 
        /// </summary>
        public BusinessObjectState State
        {
            get
            {
                return this.f_State;
            }
        }

        /// <summary>
        ///  Indexer to access extended Properties
        /// </summary>
        public object this[string PropertyName]
        {
            get
            {
                return this.GetType().GetProperty(PropertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).GetValue(this, null);
            }
            set
            {
                this.GetType().GetProperty(PropertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).SetValue(this, value, null);
            }
        }

        /// <summary>
        ///  filter used for collection operations
        /// </summary>
        public List<DataFilter> Filters
        {
            get
            {
                return this.f_DLProduct.Filters;
            }
        }


        /// <summary>
        /// sorts used for collection operations
        /// </summary>
        public List<DataSort> Sorts
        {
            get
            {
                return this.f_DLProduct.Sorts;
            }
        }
        #endregion

        #region methods


        /// <summary>
        /// Insert the object in the dataBase
        /// </summary>
        public virtual int Insert(string[] properties, string[] autoDateProperties)
        {
            int count = 0;
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeInsertGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeInsert(e);
                if (!e.Cancel)
                {
                    count = this.f_DLProduct.Insert(properties, autoDateProperties);
                    this.f_Error = this.f_DLProduct.Error;
                    BLProduct.ONAfterInsertGlobal(this, this.f_Error);
                    this.ONAfterInsert();
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
            if (this.f_Error == null)
            {
                this.f_State = BusinessObjectState.Loaded;
            }
            return count;
        }
        /// <summary>
        /// Insert the object in the dataBase using settings
        /// </summary>
        public virtual int Insert(string[] properties, string[] autoDateProperties, Settings setting)
        {
            int count = 0;
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeInsertGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeInsert(e);
                if (!e.Cancel)
                {
                    count = this.f_DLProduct.Insert(properties, autoDateProperties, setting);
                    this.f_Error = this.DLProduct.Error;
                    BLProduct.ONAfterInsertGlobal(this, this.f_Error);
                    this.ONAfterInsert();
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
            if (this.f_Error == null)
            {
                this.f_State = BusinessObjectState.Loaded;
            }
            return count;

        }


        /// <summary>
        ///Update the object in the dataBase
        /// <summary>
        internal virtual int Update(string[] properties, string[] autoDateProperties)
        {
            int count = 0;
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeUpdateGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeUpdate(e);
                if (!e.Cancel)
                {
                    count = this.f_DLProduct.Update(properties, autoDateProperties);
                    this.f_Error = this.DLProduct.Error;
                    BLProduct.ONAfterUpdateGlobal(this, this.f_Error);
                    this.ONAfterUpdate();
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
            if (this.f_Error == null)
            {
                this.f_State = BusinessObjectState.Loaded;
            }
            return count;
        }
        /// <summary>
        ///Update the object in the dataBase using settings
        /// <summary>
        internal virtual int Update(string[] properties, string[] autoDateProperties, Settings setting)
        {
            int count = 0;
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeUpdateGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeUpdate(e);
                if (!e.Cancel)
                {
                    count = this.f_DLProduct.Update(properties, autoDateProperties, setting);
                    this.f_Error = this.DLProduct.Error;
                    BLProduct.ONAfterUpdateGlobal(this, this.f_Error);
                    this.ONAfterUpdate();
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
            if (this.f_Error == null)
            {
                this.f_State = BusinessObjectState.Loaded;
            }
            return count;
        }
        /// <summary>
        /// Update by some properties 
        /// </summary>
        internal virtual int UpdateByProperties(string[] properties, string[] autoDateProperties, string[] filterProperties)
        {
            this.Filters.Clear();
            if (filterProperties.Length > 0)
            {
                for (int i = 0; i < filterProperties.Length; i++)
                {
                    Type t=this.GetType().GetProperty(filterProperties[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).PropertyType;
                    CustomersSuppliersDataLayer.DataFilter filter = new DataFilter(LogicalOperators.And, filterProperties[i], FilterOperators.Equal, this[filterProperties[i]], t);
                    this.Filters.Add(filter);
                }
            }
            return this.Update(properties, autoDateProperties);
        }
        /// <summary>
        /// Update by some properties using settings
        /// </summary>
        internal virtual int UpdateByProperties(string[] properties, string[] autoDateProperties, string[] filterProperties, Settings setting)
        {
            this.Filters.Clear();
            if (filterProperties.Length > 0)
            {
                for (int i = 0; i < filterProperties.Length; i++)
                {
                    Type t = this.GetType().GetProperty(filterProperties[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).PropertyType;
                    CustomersSuppliersDataLayer.DataFilter filter = new DataFilter(LogicalOperators.And, filterProperties[i], FilterOperators.Equal, this[filterProperties[i]],t);
                    this.Filters.Add(filter);
                }
            }
            return this.Update(properties, autoDateProperties, setting);
        }
        /// <summary>
        /// Update by Identifiers only
        /// </summary>
        public virtual int UpdateByIdentifiers(string[] properties, string[] autoDateProperties)
        {
            return this.UpdateByProperties(properties, autoDateProperties, BLProduct.PropertiesNames.Identifiers);
        }
        /// <summary>
        /// Update by Identifiers only using settings
        /// </summary>
        public virtual int UpdateByIdentifiers(string[] properties, string[] autoDateProperties, Settings setting)
        {
            return this.UpdateByProperties(properties, autoDateProperties, BLProduct.PropertiesNames.Identifiers, setting);
        }




        /// <summary>
        ///InsertORUpdate the object in the dataBase
        /// <summary>
        internal virtual int InsertORUpdate(string[] propertiesInsert, string[] propertiesUpdate, string[] autoDateInsert, string[] autoDateUpadte, ref bool inserted)
        {
            int count = 0;
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeInsert_UpdateGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeInsert_Update(e);
                if (!e.Cancel)
                {
                    count = this.f_DLProduct.Insert_Update(propertiesInsert, propertiesUpdate, autoDateInsert, autoDateUpadte, ref inserted);
                    this.f_Error = this.f_DLProduct.Error;
                    if (inserted)
                    {
                        BLProduct.ONAfterInsertGlobal(this, this.f_Error);
                        this.ONAfterInsert();
                    }
                    else
                    {
                        BLProduct.ONAfterUpdateGlobal(this, this.f_Error);
                        this.ONAfterUpdate();
                    }
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
            if (this.f_Error == null)
            {
                this.f_State = BusinessObjectState.Loaded;
            }
            return count;
        }
        /// <summary>
        ///InsertORUpdate the object in the dataBase using settings
        /// <summary>
        internal virtual int InsertORUpdate(string[] propertiesInsert, string[] propertiesUpdate, string[] autoDateInsert, string[] autoDateUpadte, ref bool inserted, Settings setting)
        {
            int count = 0;
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeInsert_UpdateGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeInsert_Update(e);
                if (!e.Cancel)
                {
                    count = this.f_DLProduct.Insert_Update(propertiesInsert, propertiesUpdate, autoDateInsert, autoDateUpadte, ref inserted, setting);
                    this.f_Error = this.f_DLProduct.Error;
                    if (inserted)
                    {
                        BLProduct.ONAfterInsertGlobal(this, this.f_Error);
                        this.ONAfterInsert();
                    }
                    else
                    {
                        BLProduct.ONAfterUpdateGlobal(this, this.f_Error);
                        this.ONAfterUpdate();
                    }
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
            if (this.f_Error == null)
            {
                this.f_State = BusinessObjectState.Loaded;
            }
            return count;
        }
        /// <summary>
        /// InsertORUpdate by some properties 
        /// </summary>
        internal virtual int InsertORUpdateByProperties(string[] propertiesInsert, string[] propertiesUpdate, string[] autoDateInsert, string[] autoDateUpadte, string[] filterProperties, ref bool inserted)
        {
            this.Filters.Clear();
            if (filterProperties.Length > 0)
            {
                for (int i = 0; i < filterProperties.Length; i++)
                {
                    Type t = this.GetType().GetProperty(filterProperties[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).PropertyType;
                    CustomersSuppliersDataLayer.DataFilter filter = new DataFilter(LogicalOperators.And, filterProperties[i], FilterOperators.Equal, this[filterProperties[i]],t);
                    this.Filters.Add(filter);
                }
            }
            return this.InsertORUpdate(propertiesInsert, propertiesUpdate, autoDateInsert, autoDateUpadte, ref inserted);
        }
        /// <summary>
        /// InsertORUpdate by some properties using settings
        /// </summary>
        internal virtual int InsertORUpdateByProperties(string[] propertiesInsert, string[] propertiesUpdate, string[] autoDateInsert, string[] autoDateUpadte, string[] filterProperties, ref bool inserted, Settings setting)
        {
            this.Filters.Clear();
            if (filterProperties.Length > 0)
            {
                for (int i = 0; i < filterProperties.Length; i++)
                {
                    Type t = this.GetType().GetProperty(filterProperties[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).PropertyType;
                    CustomersSuppliersDataLayer.DataFilter filter = new DataFilter(LogicalOperators.And, filterProperties[i], FilterOperators.Equal, this[filterProperties[i]],t);
                    this.Filters.Add(filter);
                }
            }
            return this.InsertORUpdate(propertiesInsert, propertiesUpdate, autoDateInsert, autoDateUpadte, ref inserted, setting);
        }
        /// <summary>
        /// InsertORUpdate by Identifiers only
        /// </summary>
        public virtual int InsertORUpdateByIdentifiers(string[] propertiesInsert, string[] propertiesUpdate, string[] autoDateInsert, string[] autoDateUpadte, ref bool inserted)
        {
            return this.InsertORUpdateByProperties(propertiesInsert, propertiesUpdate, autoDateInsert, autoDateUpadte, BLProduct.PropertiesNames.Identifiers, ref inserted);
        }
        /// <summary>
        /// InsertORUpdate by Identifiers only using settings
        /// </summary>
        public virtual int InsertORUpdateByIdentifiers(string[] propertiesInsert, string[] propertiesUpdate, string[] autoDateInsert, string[] autoDateUpadte, ref bool inserted, Settings setting)
        {
            return this.InsertORUpdateByProperties(propertiesInsert, propertiesUpdate, autoDateInsert, autoDateUpadte, BLProduct.PropertiesNames.Identifiers, ref inserted, setting);
        }



        /// <summary>
        ///delete the object from the dataBase
        /// <summary>
        internal virtual int Delete()
        {
            int count = 0;
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeDeleteGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeDelete(e);
                if (!e.Cancel)
                {
                    count = this.f_DLProduct.Delete();
                    this.f_Error = this.f_DLProduct.Error;
                    BLProduct.ONAfterDeleteGlobal(this, this.f_Error);
                    this.ONAfterDelete();
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
            if (this.f_Error == null)
            {
                this.f_State = BusinessObjectState.CreatedModified;
            }
            return count;
        }
        /// <summary>
        ///delete the object from the dataBase using settings
        /// <summary>
        internal virtual int Delete(Settings setting)
        {
            int count = 0;
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeDeleteGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeDelete(e);
                if (!e.Cancel)
                {
                    count = this.f_DLProduct.Delete(setting);
                    this.f_Error = this.f_DLProduct.Error;
                    BLProduct.ONAfterDeleteGlobal(this, this.f_Error);
                    this.ONAfterDelete();
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
            if (this.f_Error == null)
            {
                this.f_State = BusinessObjectState.CreatedModified;
            }
            return count;
        }
        /// <summary>
        /// Delete by some properties 
        /// </summary>
        internal virtual int DeleteByProperties(string[] filterProperties)
        {
            this.Filters.Clear();
            if (filterProperties.Length > 0)
            {
                for (int i = 0; i < filterProperties.Length; i++)
                {
                    Type t = this.GetType().GetProperty(filterProperties[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).PropertyType;
                    CustomersSuppliersDataLayer.DataFilter filter = new DataFilter(LogicalOperators.And, filterProperties[i], FilterOperators.Equal, this[filterProperties[i]],t);
                    this.Filters.Add(filter);
                }
            }
            return this.Delete();
        }
        /// <summary>
        /// Delete by some properties using settings
        /// </summary>
        internal virtual int DeleteByProperties(string[] filterProperties, Settings setting)
        {
            this.Filters.Clear();
            if (filterProperties.Length > 0)
            {
                for (int i = 0; i < filterProperties.Length; i++)
                {
                    Type t = this.GetType().GetProperty(filterProperties[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).PropertyType;
                    CustomersSuppliersDataLayer.DataFilter filter = new DataFilter(LogicalOperators.And, filterProperties[i], FilterOperators.Equal, this[filterProperties[i]], t);
                    this.Filters.Add(filter);
                }
            }
            return this.Delete(setting);
        }
        /// <summary>
        /// Delete by Identifiers only
        /// </summary>
        public virtual int DeleteByIdentifiers()
        {
            return this.DeleteByProperties(BLProduct.PropertiesNames.Identifiers);
        }
        /// <summary>
        /// Delete by Identifiers only using settings
        /// </summary>
        public virtual int DeleteByIdentifiers(Settings setting)
        {
            return this.DeleteByProperties(BLProduct.PropertiesNames.Identifiers, setting);
        }
        /// <summary>
        /// mark the object as deleted used in autosave to delete it
        /// </summary>
        public void MarkAsDeleted()
        {
            this.f_State = BusinessObjectState.MarkAsDeleted;
        }

        /// <summary>
        /// Default save object to dataBase of the object (return true if insert operation is done)
        /// </summary>
        public virtual bool DefaultSave(SaveType saveType)
        {
            if (saveType == SaveType.Insert)
            {
                this.Insert(BLProduct.PropertiesNames.DefaultInsert, BLProduct.PropertiesNames.AutoDateInsert);
                return true;
            }
            else if (saveType == SaveType.Update)
            {
                this.UpdateByIdentifiers(BLProduct.PropertiesNames.DefaultUpdate, BLProduct.PropertiesNames.AutoDateUpdate);
                return false;
            }
            else if (saveType == SaveType.Insert_Update)
            {
                bool inserted = false;
                this.InsertORUpdateByIdentifiers(BLProduct.PropertiesNames.DefaultInsert, BLProduct.PropertiesNames.DefaultUpdate, BLProduct.PropertiesNames.AutoDateInsert, BLProduct.PropertiesNames.AutoDateUpdate, ref inserted);
                return inserted;
            }
            else if (saveType == SaveType.Delete)
            {
                this.DeleteByIdentifiers();
                return false;
            }
            return false;
        }
        /// <summary>
        /// Default save object to dataBase of the object using setting (return true if insert operation is done)
        /// </summary>
        public virtual bool DefaultSave(SaveType saveType, Settings setting)
        {
            if (saveType == SaveType.Insert)
            {
                this.Insert(BLProduct.PropertiesNames.DefaultInsert, BLProduct.PropertiesNames.AutoDateInsert, setting);
                return true;
            }
            else if (saveType == SaveType.Update)
            {
                this.UpdateByIdentifiers(BLProduct.PropertiesNames.DefaultUpdate, BLProduct.PropertiesNames.AutoDateUpdate, setting);
                return false;
            }
            else if (saveType == SaveType.Insert_Update)
            {
                bool inserted = false;
                this.InsertORUpdateByIdentifiers(BLProduct.PropertiesNames.DefaultInsert, BLProduct.PropertiesNames.DefaultUpdate, BLProduct.PropertiesNames.AutoDateInsert, BLProduct.PropertiesNames.AutoDateUpdate, ref inserted, setting);
                return inserted;
            }
            else if (saveType == SaveType.Delete)
            {
                this.DeleteByIdentifiers(setting);
                return false;
            }
            return false;
        }


        /// <summary>
        /// auto save object to dataBase depends on state of the object 
        /// </summary>
        public virtual void AutoSave()
        {
            if (this.f_State == BusinessObjectState.Created || this.f_State == BusinessObjectState.CreatedModified)
            {
                this.Insert(BLProduct.PropertiesNames.DefaultInsert, BLProduct.PropertiesNames.AutoDateInsert);
            }
            else if (this.f_State == BusinessObjectState.loadedModified)
            {
                this.UpdateByIdentifiers(BLProduct.PropertiesNames.DefaultUpdate, BLProduct.PropertiesNames.AutoDateUpdate);
            }
            else if (this.f_State == BusinessObjectState.MarkAsDeleted)
            {
                this.DeleteByIdentifiers();
            }
        }
        /// <summary>
        /// auto save object to dataBase depends on state of the object using settings
        /// </summary>
        public virtual void AutoSave(Settings setting)
        {
            if (this.f_State == BusinessObjectState.Created || this.f_State == BusinessObjectState.CreatedModified)
            {
                this.Insert(BLProduct.PropertiesNames.DefaultInsert, BLProduct.PropertiesNames.AutoDateInsert, setting);
            }
            else if (this.f_State == BusinessObjectState.loadedModified)
            {
                this.UpdateByIdentifiers(BLProduct.PropertiesNames.DefaultUpdate, BLProduct.PropertiesNames.AutoDateUpdate, setting);
            }
            else if (this.f_State == BusinessObjectState.MarkAsDeleted)
            {
                this.DeleteByIdentifiers(setting);
            }
        }



        /// <summary>
        /// load data
        /// </summary>
        internal virtual void Load()
        {
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeLoadGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeLoad(e);
                if (!e.Cancel)
                {
                    bool isLoaded = this.f_DLProduct.LoadData();
                    this.f_Error = this.DLProduct.Error;
                    if (this.f_Error == null && isLoaded)
                    {
                        this.f_State = BusinessObjectState.Loaded;
                        this.ONAfterLoad();
                        BLProduct.ONAfterLoadGlobal(this, this.f_Error);
                    }
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
        }
        /// <summary>
        /// load data using settins
        /// </summary>
        internal virtual void Load(Settings setting)
        {
            CancelEventArgs e = new CancelEventArgs(false);
            BLProduct.ONBeforeLoadGlobal(this, e);
            if (!e.Cancel)
            {
                this.ONBeforeLoad(e);
                if (!e.Cancel)
                {
                    bool isLoaded = this.f_DLProduct.LoadData(setting);
                    this.f_Error = this.DLProduct.Error;
                    if (this.f_Error == null && isLoaded)
                    {
                        this.f_State = BusinessObjectState.Loaded;
                        this.ONAfterLoad();
                        BLProduct.ONAfterLoadGlobal(this, this.f_Error);
                    }
                }
                else
                {
                    this.f_Error = new Exception("Action was Canceled");
                }
            }
            else
            {
                this.f_Error = new Exception("Action was Canceled");
            }
        }
        /// <summary>
        /// load by some properties 
        /// </summary>
        internal virtual void LoadByProperties(string[] filterProperties)
        {
            this.Filters.Clear();
            if (filterProperties.Length > 0)
            {
                for (int i = 0; i < filterProperties.Length; i++)
                {
                    Type t = this.GetType().GetProperty(filterProperties[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).PropertyType;
                    CustomersSuppliersDataLayer.DataFilter filter = new DataFilter(LogicalOperators.And, filterProperties[i], FilterOperators.Equal, this[filterProperties[i]], t);
                    this.Filters.Add(filter);
                }
            }
            this.Load();
        }
        /// <summary>
        /// load by some properties using settings
        /// </summary>
        internal virtual void LoadByProperties(string[] filterProperties, Settings setting)
        {
            this.Filters.Clear();
            if (filterProperties.Length > 0)
            {
                for (int i = 0; i < filterProperties.Length; i++)
                {
                    Type t = this.GetType().GetProperty(filterProperties[i], BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).PropertyType;
                    CustomersSuppliersDataLayer.DataFilter filter = new DataFilter(LogicalOperators.And, filterProperties[i], FilterOperators.Equal, this[filterProperties[i]], t);
                    this.Filters.Add(filter);
                }
            }
            this.Load(setting);
        }
        /// <summary>
        /// load by Identifiers only
        /// </summary>
        public virtual void LoadByIdentifiers()
        {
            this.LoadByProperties(BLProduct.PropertiesNames.Identifiers);
        }
        /// <summary>
        /// load by Identifiers only using settings
        /// </summary>
        public virtual void LoadByIdentifiers(Settings setting)
        {
            this.LoadByProperties(BLProduct.PropertiesNames.Identifiers, setting);
        }
        /// <summary>
        /// test if the kes are the same in both objects
        /// </summary>
        public virtual bool IsIdentifiersEqual(BLProduct otherItem)
        {
            bool iseqal = true;
            for (int i = 0; i < BLProduct.PropertiesNames.Identifiers.Length; i++)
            {
                if (this[BLProduct.PropertiesNames.Identifiers[i]] == null
                    || this[BLProduct.PropertiesNames.Identifiers[i]] != otherItem[BLProduct.PropertiesNames.Identifiers[i]])
                {
                    iseqal = false;
                }
            }
            return iseqal;
        }


        /// <summary>
        /// add filter used with collections operations
        /// </summary>
        public void AddFilter(LogicalOperators logicalOperator, string property, FilterOperators filterOperator, object value,Type t)
        {
            DataFilter filter = new DataFilter(logicalOperator, property, filterOperator, value, t);
            this.Filters.Add(filter);
        }
        /// <summary>
        /// add sort used with collections operations
        /// </summary>
        public void AddSort(string property, bool descending)
        {
            DataSort sort = new DataSort(property, descending);
            this.Sorts.Add(sort);
        }



        /// <summary>
        /// Export the object to other object (if no prperties is defined all properties is Exported)
        /// </summary>
        public void ExportTo(BLProduct otherItem, string[] Properties)
        {
            for (int i = 0; i < Properties.Length; i++)
            {
                otherItem[Properties[i]] = this[Properties[i]];
            }
            otherItem.f_State = this.f_State;
        }
        /// <summary>
        /// Import the object to other object (if no prperties is defined all properties is Imported)
        /// </summary>
        public void ImportFrom(BLProduct otherItem, string[] properties)
        {
            otherItem.ExportTo(this, properties);
        }


        /// <summary>
        /// store the object in named restore point
        /// </summary>
        public void SetRestorePoint(string RestorePointName)
        {
            BLProduct otherItem = new BLProduct();
            otherItem.ImportFrom(this, BLProduct.PropertiesNames.All);
            otherItem.f_Error = this.f_Error;
            otherItem.extendedProperties = new Dictionary<string, object>(this.extendedProperties);
            this.RestorePoints.Add(RestorePointName.ToLower(), otherItem);
        }
        /// <summary>
        /// restore the object from named restore point
        /// </summary>
        public void RestoreFrom(string RestorePointName)
        {
            BLProduct otherItem = this.RestorePoints[RestorePointName.ToLower()];
            this.ImportFrom(otherItem, BLProduct.PropertiesNames.All);
            this.f_Error = otherItem.f_Error;
            this.extendedProperties = new Dictionary<string, object>(this.extendedProperties);
        }
        /// <summary>
        /// clear all restore popints
        /// </summary>
        public void ClearRestorePoints(string name)
        {
            this.RestorePoints.Clear();
        }

        #endregion

        #region Events
        public event PropertyChangedEventHandler PropertyChanged;

        public event CancelEventHandler BeforeLoad;
        public event CancelEventHandler BeforeInsert;
        public event CancelEventHandler BeforeUpdate;
        public event CancelEventHandler BeforeDelete;
        public event CancelEventHandler BeforeInsert_Update;
        public event EventHandler AfterLoad;
        public event EventHandler AfterInsert;
        public event EventHandler AfterUpdate;
        public event EventHandler AfterDelete;


        public static event CancelEventHandler BeforeLoadGlobal;
        public static event CancelEventHandler BeforeInsertGlobal;
        public static event CancelEventHandler BeforeUpdateGlobal;
        public static event CancelEventHandler BeforeDeleteGlobal;
        public static event CancelEventHandler BeforeInsert_UpdateGlobal;
        public static event EventHandler AfterLoadGlobal;
        public static event EventHandler AfterInsertGlobal;
        public static event EventHandler AfterUpdateGlobal;
        public static event EventHandler AfterDeleteGlobal;
        #endregion

        #region events raising
        /// <summary> 
        /// raise the event PropertyChanged
        /// </summary> 
        protected virtual void OnPropertyChanged(string name)
        {
            if (this.f_State == BusinessObjectState.Created)
            {
                this.f_State = BusinessObjectState.CreatedModified;
            }
            if (this.f_State == BusinessObjectState.Loaded)
            {
                this.f_State = BusinessObjectState.loadedModified;
            }

            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        /// <summary> 
        /// raise the event BeforeLoad
        /// </summary> 
        protected virtual void ONBeforeLoad(CancelEventArgs e)
        {
            if (this.BeforeLoad != null)
            {
                this.BeforeLoad(this, e);
            }
        }
        /// <summary> 
        /// raise the event BeforeInsert 
        /// </summary> 
        protected virtual void ONBeforeInsert(CancelEventArgs e)
        {
            if (this.BeforeInsert != null)
            {
                this.BeforeInsert(this, e);
            }
        }
        /// <summary> 
        /// raise the event BeforeUpdate 
        /// </summary> 
        protected virtual void ONBeforeUpdate(CancelEventArgs e)
        {
            if (this.BeforeUpdate != null)
            {
                this.BeforeUpdate(this, e);
            }
        }
        /// <summary> 
        /// raise the event BeforeDelete 
        /// </summary> 
        protected virtual void ONBeforeDelete(CancelEventArgs e)
        {
            if (this.BeforeDelete != null)
            {
                this.BeforeDelete(this, e);
            }
        }
        /// <summary> 
        /// raise the event BeforeInsert_Update 
        /// </summary> 
        protected virtual void ONBeforeInsert_Update(CancelEventArgs e)
        {
            if (this.BeforeInsert_Update != null)
            {
                this.BeforeInsert_Update(this, e);
            }
        }
        /// <summary> 
        /// raise the event BeforeLoad
        /// </summary> 
        protected virtual void ONAfterLoad()
        {
            if (this.AfterLoad != null)
            {
                this.AfterLoad(this, new EventArgs());
            }
        }
        /// <summary> 
        /// raise the event AfterInsert 
        /// </summary> 
        protected virtual void ONAfterInsert()
        {
            if (this.f_Error == null && this.AfterInsert != null)
            {
                this.AfterInsert(this, new EventArgs());
            }
        }
        /// <summary> 
        /// raise the event AfterUpdate 
        /// </summary> 
        protected virtual void ONAfterUpdate()
        {
            if (this.f_Error == null && this.AfterUpdate != null)
            {
                this.AfterUpdate(this, new EventArgs());
            }
        }
        /// <summary> 
        /// raise the event AfterDelete 
        /// </summary> 
        protected virtual void ONAfterDelete()
        {
            if (this.f_Error == null && this.AfterDelete != null)
            {
                this.AfterDelete(this, new EventArgs());
            }
        }


        /// <summary> 
        /// raise the event BeforeLoadGlobal  
        /// </summary> 
        protected static void ONBeforeLoadGlobal(BLProduct sender, CancelEventArgs e)
        {
            if (BLProduct.BeforeLoadGlobal != null)
            {
                BLProduct.BeforeLoadGlobal(sender, e);
            }
        }
        /// <summary> 
        /// raise the event BeforeInsertGlobal  
        /// </summary> 
        protected static void ONBeforeInsertGlobal(BLProduct sender, CancelEventArgs e)
        {
            if (BLProduct.BeforeInsertGlobal != null)
            {
                BLProduct.BeforeInsertGlobal(sender, e);
            }
        }
        /// <summary> 
        /// raise the event BeforeUpdateGlobal  
        /// </summary> 
        protected static void ONBeforeUpdateGlobal(BLProduct sender, CancelEventArgs e)
        {
            if (BLProduct.BeforeUpdateGlobal != null)
            {
                BLProduct.BeforeUpdateGlobal(sender, e);
            }
        }
        /// <summary> 
        /// raise the event BeforeDeleteGlobal  
        /// </summary> 
        protected static void ONBeforeDeleteGlobal(BLProduct sender, CancelEventArgs e)
        {
            if (BLProduct.BeforeDeleteGlobal != null)
            {
                BLProduct.BeforeDeleteGlobal(sender, e);
            }
        }
        /// <summary> 
        /// raise the event BeforeInsert_UpdateGlobal  
        /// </summary> 
        protected static void ONBeforeInsert_UpdateGlobal(BLProduct sender, CancelEventArgs e)
        {
            if (BLProduct.BeforeInsert_UpdateGlobal != null)
            {
                BLProduct.BeforeInsert_UpdateGlobal(sender, e);
            }
        }
        /// <summary> 
        /// raise the event AfterLoadGlobal  
        /// </summary> 
        protected static void ONAfterLoadGlobal(BLProduct sender, Exception error)
        {
            if (error == null && BLProduct.AfterLoadGlobal != null)
            {
                BLProduct.AfterLoadGlobal(sender, new EventArgs());
            }
        }
        /// <summary> 
        /// raise the event AfterInsertGlobal  
        /// </summary> 
        protected static void ONAfterInsertGlobal(BLProduct sender, Exception error)
        {
            if (error == null && BLProduct.AfterInsertGlobal != null)
            {
                BLProduct.AfterInsertGlobal(sender, new EventArgs());
            }
        }
        /// <summary> 
        /// raise the event AfterUpdateGlobal  
        /// </summary> 
        protected static void ONAfterUpdateGlobal(BLProduct sender, Exception error)
        {
            if (error == null && BLProduct.AfterUpdateGlobal != null)
            {
                BLProduct.AfterUpdateGlobal(sender, new EventArgs());
            }
        }
        /// <summary> 
        /// raise the event AfterDeleteGlobal  
        /// </summary> 
        protected static void ONAfterDeleteGlobal(BLProduct sender, Exception error)
        {
            if (error == null && BLProduct.AfterDeleteGlobal != null)
            {
                BLProduct.AfterDeleteGlobal(sender, new EventArgs());
            }
        }

        #endregion

        #region propertiesNames
        /// <summary>
        /// contains properties names for the object (used in binding)
        /// </summary>
        public partial class PropertiesNames
        {
            private static string[] f_Identifiers = new string[]
            {
                BLProduct.PropertiesNames.Product_ID
            };
            /// <summary>
            /// return identifirs properties names in the object
            /// </summary>
            public static string[] Identifiers
            {
                get
                {
                    return BLProduct.PropertiesNames.f_Identifiers;
                }
            }

            private static string[] f_DefaultInsert = new string[]
            {
                BLProduct.PropertiesNames.Product_ID, 
                
                BLProduct.PropertiesNames.Product_Code, 
                
                BLProduct.PropertiesNames.ProductClassification_ID, 
                
                BLProduct.PropertiesNames.Product_NameAr, 
                
                BLProduct.PropertiesNames.Product_NameEn, 
                
                BLProduct.PropertiesNames.Product_Notes, 
                
                BLProduct.PropertiesNames.Product_Search
            };
            /// <summary>
            /// return default properties names for insert
            /// </summary>
            public static string[] DefaultInsert
            {
                get
                {
                    return BLProduct.PropertiesNames.f_DefaultInsert;
                }
            }

            private static string[] f_AutoDateInsert = new string[]
            {
                
            };
            /// <summary>
            /// return AutoDate properties names for insert
            /// </summary>
            public static string[] AutoDateInsert
            {
                get
                {
                    return BLProduct.PropertiesNames.f_AutoDateInsert;
                }
            }


            private static string[] f_DefaultUpdate = new string[]
            {
                BLProduct.PropertiesNames.Product_Code, 
                
                BLProduct.PropertiesNames.ProductClassification_ID, 
                
                BLProduct.PropertiesNames.Product_NameAr, 
                
                BLProduct.PropertiesNames.Product_NameEn, 
                
                BLProduct.PropertiesNames.Product_Notes, 
                
                BLProduct.PropertiesNames.Product_Search
            };
            /// <summary>
            /// return default properties names for Update
            /// </summary>
            public static string[] DefaultUpdate
            {
                get
                {
                    return BLProduct.PropertiesNames.f_DefaultUpdate;
                }
            }

            private static string[] f_AutoDateUpdate = new string[]
            {
                
            };
            /// <summary>
            /// return AutoDate properties names for Update
            /// </summary>
            public static string[] AutoDateUpdate
            {
                get
                {
                    return BLProduct.PropertiesNames.f_AutoDateUpdate;
                }
            }


            private static string[] f_All = new string[]
            {
                BLProduct.PropertiesNames.Product_RowNumber, 
                BLProduct.PropertiesNames.Product_ID, 
                BLProduct.PropertiesNames.Product_Code, 
                BLProduct.PropertiesNames.ProductClassification_ID, 
                BLProduct.PropertiesNames.Product_NameAr, 
                BLProduct.PropertiesNames.Product_NameEn, 
                BLProduct.PropertiesNames.Product_Notes, 
                BLProduct.PropertiesNames.Product_Search, 
                BLProduct.PropertiesNames.Product_TimeStamp
            };
            /// <summary>
            /// return All properties names in the object
            /// </summary>
            public static string[] All
            {
                get
                {
                    return BLProduct.PropertiesNames.f_All;
                }
            }


            public static string Product_RowNumber
            {
                get
                {
                    return "Product_RowNumber";
                }
            }
            public static string Product_ID
            {
                get
                {
                    return "Product_ID";
                }
            }
            public static string Product_Code
            {
                get
                {
                    return "Product_Code";
                }
            }
            public static string ProductClassification_ID
            {
                get
                {
                    return "ProductClassification_ID";
                }
            }
            public static string Product_NameAr
            {
                get
                {
                    return "Product_NameAr";
                }
            }
            public static string Product_NameEn
            {
                get
                {
                    return "Product_NameEn";
                }
            }
            public static string Product_Notes
            {
                get
                {
                    return "Product_Notes";
                }
            }
            public static string Product_Search
            {
                get
                {
                    return "Product_Search";
                }
            }
            public static string Product_TimeStamp
            {
                get
                {
                    return "Product_TimeStamp";
                }
            }

            //internal static object GetValue(BLProduct obj, string Property)
            //{
            //    return typeof(BLProduct).GetProperty(Property, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase).GetValue(obj, null);
            //}
        }
        #endregion

    }
}
